/*
 * time_wheel.c
 *
 *  Created on: 2015-5-15
 *      Author: likui
 */


#include "time_wheel.h"
#include "tw_timer.h"
#include "error.h"
#include <stdlib.h>
#include <stdbool.h>

/**
 * @brief 动态创建一个时间轮结构，并初始化，需要释放内存
 */
time_wheel_t *time_wheel_create()
{
#ifndef NDEBUG
	error_msg("time_wheel_create");
#endif
	time_wheel_t *tw;

	tw = (time_wheel_t *)malloc(sizeof(time_wheel_t));
	if (tw == NULL) {
		error_msg("malloc error");
		return NULL;
	}

	time_wheel_init(tw);

	return tw;
}

/**
 * @brief 初始化时间轮结构
 */
void time_wheel_init(time_wheel_t *tw)
{
	int 	i;

	tw->cur_slot = 0;

	for (i = 0; i < SLOTS_N; i++) {
		tw->slots[i] = NULL;				// 初始化每一个槽
	}
}

/**
 * @brief 销毁时间轮结构
 * @param tw
 */
void time_wheel_destroy(time_wheel_t **tw)
{
	int 	i;
	time_wheel_t *tmp = *tw;
	// 遍历所有槽，并销毁其中的定时器链表中的所有定时器
	for (i = 0; i < SLOTS_N; i++) {
		tw_timer_list_destroy(&(tmp->slots[i]));
	}
	free(tmp);
	*tw = NULL;
}

/**
 * @brief 添加指定的新时间定时器到时间轮
 * @param tw
 * @param timeout
 * @return 若成功则为定时器结构指针，若失败则为NULL
 */
tw_timer_t * time_wheel_add(time_wheel_t *tw, int timeout)
{
#ifndef NDEBUG
	error_msg("    add_timer");
#endif
	int 			ticks, time_slot, rotation;
	tw_timer_t 	*timer;

	if (timeout < 0) {
		return NULL;
	}

	ticks = 0;
	if (timeout < SI) {
		ticks = 1;
	} else {
		ticks = timeout / SI;
	}

	// 计算圈数和时间槽的位置
	rotation = ticks / SLOTS_N;
	time_slot = (tw->cur_slot + (ticks % SLOTS_N)) %SLOTS_N;

	// 创建一个定时器结构并将定时器添加到指定的时间槽链表
	timer = tw_timer_create(rotation, time_slot);
	if (timer == NULL) {
		error_msg("tw_timer_create error");
		return NULL;
	}
	tw_timer_list_add(&(tw->slots[time_slot]), timer);

	return timer;
}

void time_wheel_update_timer(time_wheel_t *tw, tw_timer_t *timer, int timeout)
{
	int 		ticks, rotation;

	if (timeout < 0 || timer == NULL) {
		return;
	}

	ticks = 0;
	if (timeout < SI) {
		ticks = 1;
	} else {
		ticks = timeout / SI;
	}

	// 计算圈数和时间槽的位置
	rotation = ticks / SLOTS_N;
	timer->rotation = rotation;

#ifndef NDEBUG
	error_msg("        update_timer: rot = %d", rotation);
#endif

}

/**
 * @brief 从时间轮中删除一个指定定时器
 * @param tw
 * @param timer
 */
void time_wheel_del_timer(time_wheel_t *tw, tw_timer_t *timer)
{
	int		ts;

	if (!timer) {
		return;
	}

	// 从时间槽的定时器链表中删除指定定时器
	ts = timer->time_slot;
	tw_timer_list_del( &(tw->slots[ts]), timer);

#ifndef NEBUG
	error_msg("            del_timer: slot = %d", ts);
#endif
}

/**
 * @brief 心跳函数
 * @param tw
 */
void time_wheel_tick(time_wheel_t *tw)
{
	tw_timer_t *tmp = tw->slots[tw->cur_slot];			// 槽的定时器链表的首地址

#ifndef NDEBUG
	error_msg("slot = %d", tw->cur_slot);
#endif
	while (tmp) {
		if (tmp->rotation > 0 ) {				// 定时器滚动数大于0
			tmp->rotation --;
			tmp = tmp->next;
		} else {									// 时间到了
			// 执行回调函数后，将定时器结构从槽中的定时器链表中删除
			tmp->cb_func(tmp->http_conn, true, tmp->epollfd);
#ifndef NDEBUG
			error_msg("        tick_del_timer: slot = %d", tmp->time_slot);
#endif
			tmp = tw_timer_list_del(&(tw->slots[tw->cur_slot]), tmp);
		}
	}
	tw->cur_slot = (tw->cur_slot + 1) % SLOTS_N;	// 滚动一个槽
}
